package mop.model;

import java.util.LinkedList;
import java.util.List;

import mop.exception.IllegalDuplicationException;
import mop.exception.IllegalIdException;


/**
 * Generic class for storage
 * Storage all data associated with the global model 
 * 
 * @author MOP Team 7
 *
 * <T extends ModelInterface> database only compatable with model entities 
 */
public class DataBase<T extends ModelInterface>  
{

	/**
	 * Creates a ProjectPool with no extra settings.
	 * Constructor must be at protected level.
	 * Allows inheritance, but no out of package creation.
	 * 
	 * @post	Projects is set to a new LinkedList.
	 */
	public DataBase()
	{
		this.datalist = new LinkedList<T>();
	}
	
	
	/***************************************************************************
	 * 							DataList
	 ***************************************************************************/
	
	/**
	 * Mutator  for the data list
	 * 
	 * @param the model you want to add
	 * @post if not a double this.contains(model) == true
	 * 
	 * @throws  IllegalDuplicationException 
	 * 			| when the id is a double return the IllegalDuplicationException
	 * 			| with the id of the model
	 */
	public void add(T model) throws IllegalDuplicationException
	{
		if(this.contains(model))
		{
			throw new IllegalDuplicationException(model.getId());
		}
		else
		{
			datalist.add(model);
		}
	}
	
	
	/**
	 * Inspector for the internal list
	 * returns the clone
	 * 
	 * @return a copy of the internal datalist
	 */
	public List<T> fetchAll()
	{
		List<T> temporary = new LinkedList<T>();
		for(T temp : datalist)
		{
			temporary.add(temp);
		}
		return temporary;
	}
	
	
	/**
	 * Inspector for the list, checks for inclusion of given trade
	 * 
	 * @param model the model you want to check for inclusion
	 * @return true if this DataBase contains the model
	 */
	public boolean contains(T model)
	{
		return datalist.contains(model);
	}
	
	
	/**
	 * Inspector for the data matching the given id
	 * 
	 * @param 	id the identification d of the string
	 * @return 	the matching data of type T
	 * @throws 	IllegalIdException 
	 * 			Thrown when the ID does not exist in the database.
	 */
	public T find(String id) 
		throws IllegalIdException
	{
		for (T temp : datalist)
		{
			if(temp.getId().equals(id))
			{
				return temp;
			}
		}
		
		throw new IllegalIdException(id);
	}

	/**
	 * Mutator for the internal list
	 * 
	 * @param id 
	 * 		the identification string of the ModelInterface implementer we want to remove
	 * 
	 * @post find(id) == null
	 * 
	 * @throws IllegalIdException
	 * 		| if the id can not be found
	 */
	public void remove(String id) throws IllegalIdException
	{
		T temp = find(id);
		if(temp == null)
		{
			throw new IllegalIdException(id);
		}
		datalist.remove(temp);
	}
	
	/**
	 * Mutator for the internal list
	 * 
	 * @param model
	 * 		the type T we want to remove
	 * 
	 * @post contains(model) == false
	 * 
	 * @throws IllegalIdException
	 */
	public void remove(T model) throws IllegalIdException
	{
		if(this.contains(model))
		{
			datalist.remove(model);
		}
		else
		{
			throw new IllegalIdException(model.getId());
		}
	}
	
	/**
	 * Convert from Id's to Types
	 * 
	 * @param ids 
	 * 		a list with id's
	 * 
	 * @throws IllegalIdException 
	 * 		| if an id cannot be found
	 * 
	 * @return a list of type T with the types in them
	 */
	public List<T> convertFromIdToList(List<String> ids) throws IllegalIdException
	{
		List<T> newlist = new LinkedList<T>();
		for(String id : ids)
		{
			T nt = find(id);
			if(nt == null) throw new IllegalIdException(id);
			
			newlist.add(nt);
		}
		return newlist;
	}
	
	
	/**
	 * A list containing fundamental data
	 */
	private List<T> datalist;
}
